package com.cx.base.day13_io.io_09_byteArrayInputOutStream.toCopyObject;

import java.io.*;

/**
 * @Author: robert.song
 * @Date: Created in 2022/5/24
 */
public class ByteArrayInputOutStream {

    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
//        基于cloneable接口实现浅拷贝、深拷贝
//        copyByClone();
//        基于bytearraystream实现深拷贝
        copyByByteArrayStream();
    }

    public static void copyByClone() throws CloneNotSupportedException {
        //        利用Object的clone方法实现拷贝，但是前提是拷贝实例要实现cloneable接口
        Teacher teacher = new Teacher();
        teacher.setName("Delacey");
        teacher.setAge(29);

        Student student1 = new Student();
        student1.setName("Dream");
        student1.setAge(18);
        student1.setTeacher(teacher);

        Student student2 = (Student) student1.clone();
        System.out.println("浅拷贝后");
//        浅拷贝是指只拷贝对象本身，但是变量共享

        System.out.println("student2: " + student2.getName());
        System.out.println("student2: " + student2.getAge());
        System.out.println("student2.getTeacher==student1.getTeacher?" + Boolean.toString(student1.getTeacher() == student2.getTeacher()));

        Student student3 = (Student) student1.deepClone();
        System.out.println("深拷贝后");
//        深拷贝是指连同拷贝对象的变量也一块拷贝
        System.out.println("student3.getTeacher==student1.getTeacher?" + Boolean.toString(student1.getTeacher() == student3.getTeacher()));
    }

    /**
     * 待拷贝对象是通过序列化实现，因而必须实现Serializable接口
     *
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private static void copyByByteArrayStream() throws IOException, ClassNotFoundException {

        Teacher teacher = new Teacher();
        teacher.setName("Delacey");
        teacher.setAge(29);

        Student student1 = new Student();
        student1.setName("Dream");
        student1.setAge(18);
        student1.setTeacher(teacher);

        Student student2 = (Student) student1.deepCloneByByteArrayStream();
        System.out.println("基于byteArrayStream深拷贝后");
        System.out.println("student2.getTeacher==student1.getTeacher?" + Boolean.toString(student1.getTeacher() == student2.getTeacher()));
        System.out.println(student1.getTeacher());
        System.out.println(student1.getTeacher_transient());
//        由于Student的teacher_transient变量加持了transient关键词，
//        因而反序列化对象的teacher_transient变量值为null
        System.out.println(student2.getTeacher());
        System.out.println(student2.getTeacher_transient());

    }


}

class Teacher implements Cloneable, Serializable {

    private static final long serialVersionUID = -6849794470754667710L;

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

class Student implements Cloneable, Serializable {

    private static final long serialVersionUID = -6849794470754667710L;

    private String name;
    private int age;
    //Object.clone方式：要序列化引用变量，该变量的类型也要实现Cloneable接口
    //byteArray方式：要序列化引用变量，该变量类型也要实现Serializable接口
    private Teacher teacher;
    //如果不想序列化该变量，加上transient关键词
    private transient Teacher teacher_transient;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Teacher getTeacher() {
        return teacher;
    }

    public Teacher getTeacher_transient() {
        return teacher_transient;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
        this.teacher_transient = teacher;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }

    protected Object deepClone() throws CloneNotSupportedException {
        Student student = (Student) super.clone();
        student.setTeacher((Teacher) student.getTeacher().clone());
        return student;
    }

    public Object deepCloneByByteArrayStream() throws IOException, ClassNotFoundException {
        // 序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);

        // 反序列化
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        Student cloneStudent = (Student) ois.readObject();
        boolean isEqual = cloneStudent ==this;
        System.out.println("ois.readObject() == this?:" + isEqual);
        return cloneStudent;
    }

}